package orm

import (
	"encoding/json"
	"errors"
	"fmt"
	"gluenet/pkg/apis"
	"gluenet/pkg/gerrors"
	"gluenet/pkg/meta"
	"gluenet/pkg/ops/dbi"
	"gluenet/pkg/ops/orm/metrics-sql"
	"gluenet/pkg/platform/glue"
	"gopkg.in/yaml.v3"
	"strconv"
	"strings"
	"time"
)

const (
	_kindApps = "application"
	_kindNode = "machine"
)

func kinds() []string {
	return []string{_kindNode, _kindApps}
}

func MetricGuids(c dbi.GlueDB, kind string) (interface{}, error) {
	var guidLists map[string]map[string]interface{}
	switch kind {
	case apis.ObjectApplication:
		var irun []meta.InstanceRunTime
		if err := c.InstanceRuntimeList(&irun); err != nil {
			if errors.Is(err, gerrors.DataNotFind) {
				return nil, nil
			}
			return nil, fmt.Errorf("list instance runtime %v", err)
		}
		guidLists = make(map[string]map[string]interface{}, len(irun))
		for _, irunv := range irun {
			var ins *meta.Instance
			if err := c.InstanceGet(irunv.AppGuid, &ins); err != nil {
				return nil, fmt.Errorf("get instance %v", err)
			}
			version, describe, err := apis.GetVersionAndDescribeFromInstance(ins)
			if err != nil {
				return nil, fmt.Errorf("get instance version failed")
			}

			guidLists[irunv.AppGuid] = map[string]interface{}{
				"name":     ins.Name,
				"platform": ins.Platform,
				"describe": describe,
				"version":  version,
			}

			var containers = map[string]interface{}{}
			switch irunv.AppPlatform {
			case apis.PlatfromGluenets:
				containersStatusStrs := strings.Split(irunv.Status, "|")

				var containerInfo = map[string]map[string]string{}
				if err := json.Unmarshal([]byte(irunv.ContainersInfo), &containerInfo); err != nil {
					return nil, fmt.Errorf("unmarshall container info failed")
				}

				for _, css := range containersStatusStrs {
					stmp := strings.Split(css, ",")
					if len(stmp) == 2 {
						containerName, containerState := stmp[0], stmp[1]
						var svc map[string]string
						srv := containerInfo[containerName]["service"]
						report := containerInfo[containerName]["report"]
						if containerState == meta.StateReady {
							svc = make(map[string]string)
							if report == "" {
								svc["perfermance_enable"] = "diable"
							} else {
								svc["perfermance_enable"] = "enable"
							}
							if srv == "" {
								svc["app_enable"] = "diable"
								svc["app"] = ""
							} else {
								svc["app_enable"] = "enable"
								svc["app"] = srv
							}
						} else {
							svc = map[string]string{
								"perfermance_enable": "diable",
								"app_enable":         "diable",
								"app":                "",
							}
						}
						containers[containerName] = svc
					}

				}
			case apis.PlatfromKubernetes:
				containersStatusStrs := strings.Split(irunv.Status, "|")
				for _, css := range containersStatusStrs {
					stmp := strings.Split(css, ",")
					if len(stmp) < 2 {
						continue
						return nil, fmt.Errorf("strlen < 2")
					}
					containerName, containerState := stmp[0], stmp[1]
					if containerState == meta.StateReady {
						containers[containerName] = map[string]string{
							"perfermance_enable": "diable",
							"app_enable":         "diable",
							"app":                "",
						}
					}
				}
			}
			guidLists[irunv.AppGuid]["containers"] = containers
		}
	case apis.ObjectMachine:
		var arun []meta.AgentRunTime
		if err := c.AgentRuntimeList(&arun); err != nil {
			return nil, err
		}

		guidLists = make(map[string]map[string]interface{}, len(arun))
		for _, v := range arun {
			host := strings.Split(v.Hosts, "|")
			hostContainersSlice := strings.Split(v.Containers, "|")
			hostContainerMap := make(map[string][]interface{})

			switch v.Platform {
			case apis.PlatfromGluenets:
				containersList, id := make([]interface{}, len(hostContainersSlice)), 0
				for _, vstr := range hostContainersSlice {
					cs := strings.Split(vstr, ",")
					if len(cs) == 2 {
						containersList[id] = map[string]string{
							"container": cs[0],
							"guid":      cs[1],
						}
						id++
					}
				}
				hostContainerMap[host[0]] = containersList

			case apis.PlatfromKubernetes:
				containersList := make(map[string][]interface{})
				for _, vstr := range hostContainersSlice {
					cs := strings.Split(vstr, ",")
					if len(cs) == 4 {
						containersList[cs[3]] = append(containersList[cs[3]], map[string]string{
							"guid":      cs[0],
							"container": cs[1],
							"pod":       cs[2],
						})
					}
				}
				for _, hostname := range host {
					hostContainerMap[hostname] = []interface{}{}
				}
				for cn, list := range containersList {
					hostContainerMap[cn] = append(hostContainerMap[cn], list...)
				}
			}

			var agent *meta.Agent
			if err := c.AgentGet(v.AgentGuid, &agent); err != nil {
				return nil, err
			}

			guidLists[v.AgentGuid] = map[string]interface{}{
				"name":     agent.Hostname,
				"platform": v.Platform,
				"hosts":    hostContainerMap,
				"area":     agent.Area,
			}
		}
	}
	return guidLists, nil
}

func MetricsList(c dbi.GlueDB) (interface{}, error) {
	var data []map[string]interface{}
	var tmpData []map[string]interface{}

	end := time.Now().Unix()
	start := end - 30
	var sql = fmt.Sprintf(metrics_sql.MetricsList, start, end)

	if err := c.MetricsQuerySQL(sql, &tmpData); err != nil {
		return nil, err
	}
	data = make([]map[string]interface{}, len(tmpData))
	for k, v := range tmpData {
		data[k] = map[string]interface{}{
			"label":    v["label"],
			"object":   v["object"],
			"platform": v["platform"],
		}
	}
	return data, nil
}

func MetricsMethod(c dbi.GlueDB, object, platform, metric, guid, method string, start, end int64) (interface{}, error) {
	var data []map[string]interface{}
	var tmpData []map[string]interface{}
	var sql string

	switch object {
	case apis.ObjectMachine:
		return nil, fmt.Errorf("don't support object now")
	case apis.ObjectApplication:
		switch platform {
		case apis.PlatfromKubernetes:
			switch method {
			case apis.MethodMaxMax:
				sql = fmt.Sprintf(metrics_sql.MaxMaxApplicationKubernetes, object, platform, metric, guid, start, end)
			case apis.MethodAvgMax:
				sql = fmt.Sprintf(metrics_sql.AvgMaxApplicationKubernetes, object, platform, metric, guid, start, end)
			case apis.MethodAvgMin:
				sql = fmt.Sprintf(metrics_sql.AvgMinApplicationKubernetes, object, platform, metric, guid, start, end)
			}
		case apis.PlatfromGluenets:
			switch method {
			case apis.MethodMaxMax:
				sql = fmt.Sprintf(metrics_sql.MaxMaxApplicationGluenets, object, platform, metric, guid, start, end)
			case apis.MethodAvgMax:
				sql = fmt.Sprintf(metrics_sql.AvgMaxApplicationGluenets, object, platform, metric, guid, start, end)
			case apis.MethodAvgMin:
				sql = fmt.Sprintf(metrics_sql.AvgMinApplicationGluenets, object, platform, metric, guid, start, end)
			}
		}
	}

	if err := c.MetricsQuerySQL(sql, &tmpData); err != nil {
		return nil, err
	}
	data = make([]map[string]interface{}, len(tmpData))

	switch object {
	case apis.ObjectMachine:
		switch platform {
		case apis.PlatfromGluenets:
		case apis.PlatfromKubernetes:
			for k, v := range tmpData {
				data[k] = map[string]interface{}{
					"time":     v["_time"],
					"label":    v["label"],
					"value":    v["_value"],
					"guid":     v["agent"],
					"hostname": v["host_name"],
					"object":   v["object"],
					"platform": v["platform"],
				}
			}
		}
	case apis.ObjectApplication:
		switch platform {
		case apis.PlatfromGluenets:
			for k, v := range tmpData {
				//gc := strings.Split(v["container"].(string), "_")
				data[k] = map[string]interface{}{
					"time":      v["_time"],
					"label":     v["name"],
					"value":     v["_value"],
					"guid":      v["application_guid"],
					"container": v["container"],
					"object":    v["object"],
					"platform":  v["platform"],
				}
			}
		case apis.PlatfromKubernetes:
			for k, v := range tmpData {
				data[k] = map[string]interface{}{
					"time":      v["_time"],
					"label":     v["label"],
					"value":     v["_value"],
					"guid":      v["application_guid"],
					"container": v["container"],
					"object":    v["object"],
					"platform":  v["platform"],
				}
			}
		}
	}

	return data, nil
}

func MetricsSum(c dbi.GlueDB, object, platform, metric, guid string, childs string, start, end int64) (interface{}, error) {
	var data []map[string]interface{}
	var tmpData []map[string]interface{}
	var sql string

	//fmt.Printf()
	switch object {
	case apis.ObjectMachine:
		switch platform {
		case apis.PlatfromGluenets:
			sql = fmt.Sprintf(metrics_sql.SumMachineGluenets, object, platform, metric, guid, childs, start, end)
		case apis.PlatfromKubernetes:
			sql = fmt.Sprintf(metrics_sql.SumMachineKubernetes, object, platform, metric, guid, childs, start, end)
		}
	case apis.ObjectApplication:
		switch platform {
		case apis.PlatfromGluenets:
			sql = fmt.Sprintf(metrics_sql.SumApplicationGluenets, object, platform, metric, guid, childs, start, end)
		case apis.PlatfromKubernetes:
			sql = fmt.Sprintf(metrics_sql.SumApplicationKubernetes, object, platform, metric, guid, childs, start, end)
		}
	}

	fmt.Printf("\n\n %v \n\n", sql)

	if err := c.MetricsQuerySQL(sql, &tmpData); err != nil {
		return nil, err
	}
	data = make([]map[string]interface{}, len(tmpData))

	switch object {
	case apis.ObjectMachine:
		switch platform {
		case apis.PlatfromGluenets:
			for k, v := range tmpData {
				data[k] = map[string]interface{}{
					"time":     v["_time"],
					"label":    v["label"],
					"value":    v["_value"],
					"guid":     v["agent_guid"],
					"hostname": childs,
					"object":   v["object"],
					"platform": v["platform"],
				}
			}
		case apis.PlatfromKubernetes:
			for k, v := range tmpData {
				data[k] = map[string]interface{}{
					"time":     v["_time"],
					"label":    v["label"],
					"value":    v["_value"],
					"guid":     v["agent_guid"],
					"hostname": childs,
					"object":   v["object"],
					"platform": v["platform"],
				}
			}
		}
	case apis.ObjectApplication:
		switch platform {
		case apis.PlatfromGluenets:
			for k, v := range tmpData {
				data[k] = map[string]interface{}{
					"time":      v["_time"],
					"label":     v["label"],
					"value":     v["_value"],
					"guid":      guid,
					"container": childs,
					"object":    v["object"],
					"platform":  v["platform"],
				}
			}
		case apis.PlatfromKubernetes:
			for k, v := range tmpData {
				data[k] = map[string]interface{}{
					"time":      v["_time"],
					"label":     v["label"],
					"value":     v["_value"],
					"guid":      v["application_guid"],
					"container": childs,
					"object":    v["object"],
					"platform":  v["platform"],
				}
			}
		}
	}
	return data, nil
}

func Metrics(c dbi.GlueDB, object, platform, metric, guid, child string, start, end int64) (interface{}, error) {
	var data []map[string]interface{}
	var tmpData []map[string]interface{}
	var sql string

	//fmt.Printf()

	switch object {
	case apis.ObjectMachine:
		switch platform {
		case apis.PlatfromGluenets:
			sql = fmt.Sprintf(metrics_sql.MachineGluenets, object, platform, metric, guid, child, start, end)
		case apis.PlatfromKubernetes:
			sql = fmt.Sprintf(metrics_sql.MachineKubernets, object, platform, metric, guid, child, start, end)
		}
	case apis.ObjectApplication:
		switch platform {
		case apis.PlatfromGluenets:
			sql = fmt.Sprintf(metrics_sql.ApplicationGluenets, object, platform, metric, guid, child, start, end)
		case apis.PlatfromKubernetes:
			sql = fmt.Sprintf(metrics_sql.ApplicationKubernets, object, platform, metric, guid, child, start, end)
		}
	}

	//fmt.Printf("\n\n %v \n\n", sql)

	if err := c.MetricsQuerySQL(sql, &tmpData); err != nil {
		return nil, err
	}
	data = make([]map[string]interface{}, len(tmpData))

	switch object {
	case apis.ObjectMachine:
		switch platform {
		case apis.PlatfromGluenets:
			for k, v := range tmpData {
				data[k] = map[string]interface{}{
					"time":     v["_time"],
					"label":    v["label"],
					"value":    v["_value"],
					"guid":     v["guid"],
					"hostname": v["host_name"],
					"object":   v["object"],
					"platform": v["platform"],
				}
			}
		case apis.PlatfromKubernetes:
			for k, v := range tmpData {
				data[k] = map[string]interface{}{
					"time":     v["_time"],
					"label":    v["label"],
					"value":    v["_value"],
					"guid":     v["agent"],
					"hostname": v["host_name"],
					"object":   v["object"],
					"platform": v["platform"],
				}
			}
		}
	case apis.ObjectApplication:
		switch platform {
		case apis.PlatfromGluenets:
			for k, v := range tmpData {
				//gc := strings.Split(v["container"].(string), "_")
				data[k] = map[string]interface{}{
					"time":      v["_time"],
					"label":     v["label"],
					"value":     v["_value"],
					"guid":      v["application_guid"],
					"container": v["container"],
					"object":    v["object"],
					"platform":  v["platform"],
				}
			}
		case apis.PlatfromKubernetes:
			for k, v := range tmpData {
				data[k] = map[string]interface{}{
					"time":      v["_time"],
					"label":     v["label"],
					"value":     v["_value"],
					"guid":      v["application_guid"],
					"container": v["container"],
					"object":    v["object"],
					"platform":  v["platform"],
				}
			}
		}
	}
	return data, nil
}

func CpuUsage(c dbi.GlueDB, kind string, guid string, child string, start, end int64) (interface{}, error) {

	switch kind {
	case _kindNode:
		var arun *meta.AgentRunTime
		if err := c.AgentRuntimeGet(guid, &arun); err != nil {
			return nil, fmt.Errorf("can't find agent %v", err)
		}

		var data = []map[string]interface{}{}
		switch arun.Platform {
		case apis.PlatfromKubernetes:
			var tmpData []map[string]interface{}
			if err := c.MetricsQuerySQL(fmt.Sprintf(metrics_sql.K8sNodeCpuUsageV2, guid, child, start, end), &tmpData); err != nil {
				return nil, err
			}

			data = make([]map[string]interface{}, len(tmpData))
			for k, v := range tmpData {
				data[k] = map[string]interface{}{
					"time":     v["_time"],
					"label":    v["name"],
					"value":    v["_value"],
					"guid":     v["agent"],
					"hostname": v["instance"],
					"object":   v["object"],
					"platform": v["platform"],
				}
			}
		case apis.PlatfromGluenets:
			// todo
			panic("impl me")
			//if err := c.MetricsQuerySQL(fmt.Sprintf(metrics_sql.GluenetsNodeCpuUsageV2, start, end, guid), &data); err != nil {
			//	return nil, err
			//}
		}
		return data, nil
	case _kindApps:
		var irun *meta.InstanceRunTime
		if err := c.InstanceRuntimeGet(guid, &irun); err != nil {
			return nil, fmt.Errorf("can't find agent %v", err)
		}

		var data []map[string]interface{}
		switch irun.AppPlatform {
		case apis.PlatfromKubernetes:
			var tmpData []map[string]interface{}
			//fmt.Printf("\n%v\n", fmt.Sprintf(metrics_sql.K8sContainerCpuUsageV2, guid, child, start, end))
			if err := c.MetricsQuerySQL(fmt.Sprintf(metrics_sql.K8sContainerCpuUsageV2, guid, child, start, end), &tmpData); err != nil {
				return nil, err
			}

			data = make([]map[string]interface{}, len(tmpData))
			for k, v := range tmpData {
				data[k] = map[string]interface{}{
					"time":      v["_time"],
					"label":     v["name"],
					"value":     v["_value"],
					"guid":      v["namespace"],
					"container": v["container"],
					"object":    v["object"],
					"platform":  v["platform"],
				}
			}
			//fmt.Printf("data: %v", data)
		case apis.PlatfromGluenets:
			// todo
			panic("impl me")
			//data = make(map[string][]map[string]interface{})
			//for k, v := range services {
			//	var dataSub map[string][]map[string]interface{}
			//	if err := c.MetricsQuerySQL(fmt.Sprintf(metrics_sql.GluenetsContainerCpuUsage, guid, k, start, end, v), &dataSub); err != nil {
			//		return nil, err
			//	}
			//	for kd, vd := range dataSub {
			//		data[kd] = vd
			//	}
			//}
		}
		return data, nil
	default:
		return nil, fmt.Errorf("kind must be in %v", kinds())
	}
}

func CpuUsageLast(c dbi.GlueDB, kind string, guid string, child string, start, end int64) (interface{}, error) {

	switch kind {
	case _kindNode:
		var arun *meta.AgentRunTime
		if err := c.AgentRuntimeGet(guid, &arun); err != nil {
			return nil, fmt.Errorf("can't find agent %v", err)
		}

		var data = []map[string]interface{}{}
		switch arun.Platform {
		case apis.PlatfromKubernetes:
			var tmpData []map[string]interface{}
			//fmt.Printf("\n\n %v \n\n ", fmt.Sprintf(metrics_sql.K8sNodeCpuUsagelastV2, guid, child, start, end))
			if err := c.MetricsQuerySQL(fmt.Sprintf(metrics_sql.K8sNodeCpuUsagelastV2, guid, child, start, end), &tmpData); err != nil {
				return nil, err
			}

			data = make([]map[string]interface{}, len(tmpData))
			for k, v := range tmpData {
				data[k] = map[string]interface{}{
					"time":     v["_time"],
					"label":    v["name"],
					"value":    v["_value"],
					"guid":     v["agent"],
					"hostname": v["instance"],
					"object":   v["object"],
					"platform": v["platform"],
				}
			}
		case apis.PlatfromGluenets:
			// todo
			panic("impl me")
			//if err := c.MetricsQuerySQL(fmt.Sprintf(metrics_sql.GluenetsNodeCpuUsageV2, start, end, guid), &data); err != nil {
			//	return nil, err
			//}
		}
		return data, nil
	case _kindApps:
		var irun *meta.InstanceRunTime
		if err := c.InstanceRuntimeGet(guid, &irun); err != nil {
			return nil, fmt.Errorf("can't find agent %v", err)
		}

		var data []map[string]interface{}
		switch irun.AppPlatform {
		case apis.PlatfromKubernetes:
			var tmpData []map[string]interface{}
			if err := c.MetricsQuerySQL(fmt.Sprintf(metrics_sql.K8sContainerCpuUsagelastV2, guid, child, start, end), &tmpData); err != nil {
				return nil, err
			}

			data = make([]map[string]interface{}, len(tmpData))
			for k, v := range tmpData {
				data[k] = map[string]interface{}{
					"time":      v["_time"],
					"label":     v["name"],
					"value":     v["_value"],
					"guid":      v["namespace"],
					"container": v["emoji-svc"],
					"object":    v["object"],
					"platform":  v["platform"],
				}
			}
		case apis.PlatfromGluenets:
			// todo
			panic("impl me")
			//data = make(map[string][]map[string]interface{})
			//for k, v := range services {
			//	var dataSub map[string][]map[string]interface{}
			//	if err := c.MetricsQuerySQL(fmt.Sprintf(metrics_sql.GluenetsContainerCpuUsage, guid, k, start, end, v), &dataSub); err != nil {
			//		return nil, err
			//	}
			//	for kd, vd := range dataSub {
			//		data[kd] = vd
			//	}
			//}
		}
		return data, nil
	default:
		return nil, fmt.Errorf("kind must be in %v", kinds())
	}
}

func MemoryUsage(c dbi.GlueDB, kind string, guid string, child string, start, end int64) (interface{}, error) {
	switch kind {
	case _kindNode:
		var arun *meta.AgentRunTime
		if err := c.AgentRuntimeGet(guid, &arun); err != nil {
			return nil, fmt.Errorf("can't find agent %v", err)
		}

		var data = []map[string]interface{}{}
		switch arun.Platform {
		case apis.PlatfromKubernetes:
			var tmpData []map[string]interface{}
			if err := c.MetricsQuerySQL(fmt.Sprintf(metrics_sql.K8sNodeMemUsageV2, guid, child, start, end), &tmpData); err != nil {
				return nil, err
			}

			data = make([]map[string]interface{}, len(tmpData))
			for k, v := range tmpData {
				data[k] = map[string]interface{}{
					"time":     v["_time"],
					"label":    v["name"],
					"value":    v["_value"],
					"guid":     v["agent"],
					"hostname": v["instance"],
					"object":   v["object"],
					"platform": v["platform"],
				}
			}
		case apis.PlatfromGluenets:
			// todo
			panic("impl me")
			//if err := c.MetricsQuerySQL(fmt.Sprintf(metrics_sql.GluenetsNodeCpuUsageV2, start, end, guid), &data); err != nil {
			//	return nil, err
			//}
		}
		return data, nil
	case _kindApps:
		var irun *meta.InstanceRunTime
		if err := c.InstanceRuntimeGet(guid, &irun); err != nil {
			return nil, fmt.Errorf("can't find agent %v", err)
		}

		var data []map[string]interface{}
		switch irun.AppPlatform {
		case apis.PlatfromKubernetes:
			var tmpData []map[string]interface{}
			//fmt.Printf("\n %v \n", fmt.Sprintf(metrics_sql.K8sNodeMemUsageV2, guid, child, start, end))
			if err := c.MetricsQuerySQL(fmt.Sprintf(metrics_sql.K8sContainerMemUsageV2, guid, child, start, end), &tmpData); err != nil {
				return nil, err
			}

			data = make([]map[string]interface{}, len(tmpData))
			for k, v := range tmpData {
				data[k] = map[string]interface{}{
					"time":      v["_time"],
					"label":     v["name"],
					"value":     v["_value"],
					"guid":      v["namespace"],
					"container": v["container"],
					"object":    v["object"],
					"platform":  v["platform"],
				}
			}
		case apis.PlatfromGluenets:
			// todo
			panic("impl me")
			//data = make(map[string][]map[string]interface{})
			//for k, v := range services {
			//	var dataSub map[string][]map[string]interface{}
			//	if err := c.MetricsQuerySQL(fmt.Sprintf(metrics_sql.GluenetsContainerCpuUsage, guid, k, start, end, v), &dataSub); err != nil {
			//		return nil, err
			//	}
			//	for kd, vd := range dataSub {
			//		data[kd] = vd
			//	}
			//}
		}
		return data, nil
	default:
		return nil, fmt.Errorf("kind must be in %v", kinds())
	}
}

func MemoryUsageLast(c dbi.GlueDB, kind string, guid string, child string, start, end int64) (interface{}, error) {
	switch kind {
	case _kindNode:
		var arun *meta.AgentRunTime
		if err := c.AgentRuntimeGet(guid, &arun); err != nil {
			return nil, fmt.Errorf("can't find agent %v", err)
		}

		var data = []map[string]interface{}{}
		switch arun.Platform {
		case apis.PlatfromKubernetes:
			var tmpData []map[string]interface{}
			if err := c.MetricsQuerySQL(fmt.Sprintf(metrics_sql.K8sNodeMemUsagelastV2, guid, child, start, end), &tmpData); err != nil {
				return nil, err
			}

			data = make([]map[string]interface{}, len(tmpData))
			for k, v := range tmpData {
				data[k] = map[string]interface{}{
					"time":     v["_time"],
					"label":    v["name"],
					"value":    v["_value"],
					"guid":     v["agent"],
					"hostname": v["instance"],
					"object":   v["object"],
					"platform": v["platform"],
				}
			}
		case apis.PlatfromGluenets:
			// todo
			panic("impl me")
			//if err := c.MetricsQuerySQL(fmt.Sprintf(metrics_sql.GluenetsNodeCpuUsageV2, start, end, guid), &data); err != nil {
			//	return nil, err
			//}
		}
		return data, nil
	case _kindApps:
		var irun *meta.InstanceRunTime
		if err := c.InstanceRuntimeGet(guid, &irun); err != nil {
			return nil, fmt.Errorf("can't find agent %v", err)
		}

		var data []map[string]interface{}
		switch irun.AppPlatform {
		case apis.PlatfromKubernetes:
			var tmpData []map[string]interface{}
			if err := c.MetricsQuerySQL(fmt.Sprintf(metrics_sql.K8sContainerMemUsagelastV2, guid, child, start, end), &data); err != nil {
				return nil, err
			}

			data = make([]map[string]interface{}, len(tmpData))
			for k, v := range tmpData {
				data[k] = map[string]interface{}{
					"time":      v["_time"],
					"label":     v["name"],
					"value":     v["_value"],
					"guid":      v["namespace"],
					"container": v["emoji-svc"],
					"object":    v["object"],
					"platform":  v["platform"],
				}
			}
		case apis.PlatfromGluenets:
			// todo
			panic("impl me")
			//data = make(map[string][]map[string]interface{})
			//for k, v := range services {
			//	var dataSub map[string][]map[string]interface{}
			//	if err := c.MetricsQuerySQL(fmt.Sprintf(metrics_sql.GluenetsContainerCpuUsage, guid, k, start, end, v), &dataSub); err != nil {
			//		return nil, err
			//	}
			//	for kd, vd := range dataSub {
			//		data[kd] = vd
			//	}
			//}
		}
		return data, nil
	default:
		return nil, fmt.Errorf("kind must be in %v", kinds())
	}
}

//func K8sNodes(c dbi.GlueDB, guid string) ([]map[string]interface{}, error) {
//	end := time.Now().Unix()
//	start := end - 3600
//
//	var data []map[string]interface{}
//	if err := c.GetK8sNodes(fmt.Sprintf(metrics_sql.KubernetsNodeName, start, end, guid), &data); err != nil {
//		return nil, err
//	}
//
//	return data, nil
//}

const (
	_nodePodContainer = `select * from k8s_pod_info where agent_guid=? and node_name=?`
)

//func K8sNodePods(c *apis.GlueContext, agentGuid, node string) ([]*meta.K8sPodInfo, error) {
//	var data []*meta.K8sPodInfo
//	if err := c.DataBase.MetaDB().SQL(_nodePodContainer, agentGuid, node).Find(&data); err != nil {
//		return nil, err
//	}
//	return data, nil
//}

//func K8sPodContainers(c dbi.GlueDB, agentGuid, appGuid, container string) ([]map[string]interface{}, error) {
//	end := time.Now().Unix()
//	start := end - 3600
//
//	var data []map[string]interface{}
//	if err := c.GetK8sPodContainers(fmt.Sprintf(metrics_sql.K8sPodContainer, agentGuid, appGuid, container, start, end), &data); err != nil {
//		return nil, err
//	}
//	return data, nil
//}

//func K8sContainerInfo(c *apis.GlueContext, containerName, guid string) ([]map[string]interface{}, error) {
//	end := time.Now().Unix()
//	start := end - 3600
//
//	var data []map[string]interface{}
//	if err := c.DataBase.GetK8sContainerInfo(fmt.Sprintf(metrics_sql.ContainerInfo, start, end, containerName, guid), &data); err != nil {
//		return nil, err
//	}
//	return data, nil
//}

func getPlatfromAndService(c dbi.GlueDB, kind string, guid string, tp string) (string, map[string]float64, error) {
	var platform string
	var services map[string]float64
	switch kind {
	case _kindNode:
		var agents *meta.Agent
		if err := c.AgentGet(guid, &agents); err != nil {
			return "", nil, fmt.Errorf("get agent error %v, or not exist", err)
		}
		tags, err := meta.DeCodeTags(agents.Tags)
		if err != nil {
			return "", nil, fmt.Errorf("decode tags %v", err)
		}
		plat, ok := tags["platform"]
		if !ok {
			return "", nil, fmt.Errorf("node don't have tag platform")
		}
		platform = plat
	case _kindApps:
		var ins *meta.Instance
		if err := c.InstanceGet(guid, &ins); err != nil {
			return "", nil, fmt.Errorf("get agent error %v", err)
		}
		platform = ins.Platform

		if platform == apis.PlatfromGluenets {
			services = make(map[string]float64)
			var gins glue.Instance
			if err := json.Unmarshal([]byte(ins.InstanceValue), &gins); err != nil {
				return "", nil, fmt.Errorf("decode gluenet instance error %v, or not exist", err)
			}
			var cts glue.Containers
			if err := yaml.Unmarshal([]byte(gins.InstanceYaml), &cts); err != nil {
				return "", nil, fmt.Errorf("decode gluenet instance error %v, or not exist", err)
			}
			for k, v := range cts.Containers {
				var size string
				switch tp {
				case "cpu":
					size = v.Cpu
				case "memory":
					size = v.Memory
				}

				cpuSize, err := strconv.ParseFloat(size, 64)
				if err != nil {
					return "", nil, fmt.Errorf("parse cpus to float64 %v", err)
				}
				services[k] = cpuSize
			}
		}
	default:
		return "", nil, fmt.Errorf("kind must be in %v", kinds())
	}

	return platform, services, nil
}

func LogsInfo(c dbi.GlueDB, platform string, guid, container string, start, stop string) (interface{}, error) {
	var data []map[string]interface{}
	switch platform {
	case apis.PlatfromGluenets:
		if err := c.GetLogs(fmt.Sprintf(metrics_sql.GluenetsContainerLogsInfo, guid, container, start, stop), &data); err != nil {
			return nil, err
		}
		var res = make([]map[string]interface{}, len(data))
		for k, v := range data {
			res[k] = map[string]interface{}{
				"label":   "logs",
				"message": v["_value"],
				"time":    v["_time"].(time.Time).Unix(),
				"type":    v["level"],
			}
		}
		return res, nil
	case apis.PlatfromKubernetes:
		if err := c.GetLogs(fmt.Sprintf(metrics_sql.K8sContainerLogsInfo, guid, container, start, stop), &data); err != nil {
			return nil, err
		}
		var res = make([]map[string]interface{}, len(data))
		for k, v := range data {
			res[k] = map[string]interface{}{
				"label":   "logs",
				"message": v["_value"],
				"time":    v["_time"].(time.Time).Unix(),
				"type":    v["level"],
			}
		}
		return res, nil
	default:
		return nil, fmt.Errorf("unknown platform")
	}
}

func LogsCounts(c dbi.GlueDB, platform string, guid, container string, start, stop, bucket string) (interface{}, error) {
	var data []map[string]interface{}
	switch platform {
	case apis.PlatfromGluenets:
		//fmt.Printf("time now", time.Now().Unix())
		//fmt.Printf(metrics_sql.GluenetsContainerLogsCounts, guid, container, start, stop, bucket)
		if err := c.GetLogs(fmt.Sprintf(metrics_sql.GluenetsContainerLogsCounts, guid, container, start, stop, bucket), &data); err != nil {
			return nil, err
		}
		var res = make([]map[string]interface{}, len(data))
		for k, v := range data {
			res[k] = map[string]interface{}{
				"label":  "logs",
				"counts": v["_value"],
				"start":  v["_start"].(time.Time).Unix(),
				"stop":   v["_stop"].(time.Time).Unix(),
				"type":   v["level"],
			}
		}
		return res, nil
	case apis.PlatfromKubernetes:
		if err := c.GetLogs(fmt.Sprintf(metrics_sql.K8sContainerLogsCounts, guid, container, start, stop, bucket), &data); err != nil {
			return nil, err
		}
		var res = make([]map[string]interface{}, len(data))
		for k, v := range data {
			//t1, err := time.Parse(time.RFC3339, v["_start"].(string))
			//if err != nil {
			//	return nil, err
			//}
			//t2, err := time.Parse(time.RFC3339, v["_stop"].(string))
			//if err != nil {
			//	return nil, err
			//}
			res[k] = map[string]interface{}{
				"label":  "logs",
				"counts": v["_value"],
				"start":  v["_start"].(time.Time).Unix(),
				"stop":   v["_stop"].(time.Time).Unix(),
				"type":   v["level"],
			}
		}
		return res, nil
	default:
		return nil, fmt.Errorf("unknown platform")
	}
}

func GetTCPOpenTotal(c dbi.GlueDB, guid string, platform string) (interface{}, error) {
	var data []map[string]interface{}
	var tmpData []map[string]interface{}
	var sql string

	//fmt.Printf("\n\n here \n\n")

	switch platform {
	case apis.PlatfromGluenets:
		return nil, fmt.Errorf("don't support")
	case apis.PlatfromKubernetes:
		end := time.Now().Unix()
		start := end - 60

		sql = fmt.Sprintf(metrics_sql.ApplicationKubernetesTcpOpenTotal, guid, start, end)
	}

	//fmt.Printf("\n\n %v \n\n", sql)

	if err := c.MetricsQuerySQL(sql, &tmpData); err != nil {
		return nil, err
	}
	data = make([]map[string]interface{}, len(tmpData))

	switch platform {
	case apis.PlatfromKubernetes:
		for k, v := range tmpData {
			data[k] = map[string]interface{}{
				"time":          v["_time"],
				"label":         v["name"],
				"value":         v["_value"],
				"guid":          v["namespace"],
				"dst_pod":       v["dst_pod"],
				"dst_container": v["dst_container"],
				"pod":           v["pod"],
				"container":     v["container"],
			}
		}
	case apis.PlatfromGluenets:
		return nil, fmt.Errorf("don't support")
	}

	return data, nil
}
